// https://www.cnblogs.com/Melville/p/19204163
// 因为更换镜子时可以任意调整朝向，所以所有需要二次访问的解都能无损地改造成一次访问的解。因此只要考虑简单路径的情况即可。以当前位置坐标和当前朝向作为状态，用
//  01bfs 求解。
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
using P = pair<int, int>;

// 方向数组：上、左、下、右
const int di[] = {-1, 0, 1, 0};
const int dj[] = {0, -1, 0, 1};

void solve() {
  int h, w;
  cin >> h >> w;

  vector<string> s(h);
  for (int i = 0; i < h; ++i)
    cin >> s[i];

  const int INF = 1001001001;

  // 距离数组：dist[i][j][v] 表示到达位置(i,j)且朝向为v的最小代价
  vector<vector<vector<int>>> dist(h,
                                   vector<vector<int>>(w, vector<int>(4, INF)));

  deque<tuple<int, int, int, int>> q; // 01BFS队列：(代价, i坐标, j坐标, 朝向)

  // 辅助函数：将状态加入队列
  auto push = [&](int i, int j, int v, int d, int cost) {
    d += cost;
    if (dist[i][j][v] <= d) // 如果已有更优解，跳过
      return;
    dist[i][j][v] = d; // 更新距离
    if (cost == 0)     // 0代价操作加入队首
      q.emplace_front(d, i, j, v);
    else // 1代价操作加入队尾
      q.emplace_back(d, i, j, v);
  };

  // 初始状态：从(0,0)位置，朝右方向(3)，代价为0开始
  push(0, 0, 3, 0, 0);

  int ans = INF;
  while (q.size()) {
    auto [d, i, j, v] = q.front();
    q.pop_front();
    if (dist[i][j][v] != d) // 如果状态已过期，跳过
      continue;

    int ov = v; // 原始朝向
    // 根据当前格子的镜子类型调整朝向
    if (s[i][j] == 'B') // B型镜子：方向异或1（上↔下，左↔右）
      ov ^= 1;
    if (s[i][j] == 'C') // C型镜子：方向异或3（上↔左，下↔右）
      ov ^= 3;

    // 尝试四个方向移动
    for (int u = 0; u < 4; ++u) {
      int ni = i + di[u], nj = j + dj[u]; // 新位置
      int cost = ov == u ? 0 : 1; // 如果朝向与移动方向一致，代价为0，否则为1

      // 检查是否到达终点（右下角之外的位置）
      if (ni == h - 1 and nj == w) {
        ans = min(ans, d + cost);
      }

      // 检查边界
      if (ni < 0 or ni >= h or nj < 0 or nj >= w)
        continue;

      // 将新状态加入队列
      push(ni, nj, u, d, cost);
    }
  }

  cout << ans << '\n';
}

int main() {
  int t;
  cin >> t;

  while (t--) // 处理多个测试用例
    solve();

  return 0;
}